package com.bookocean.infrastructure.persistence.repository;

import cn.hutool.core.util.ObjectUtil;
import cn.hutool.core.util.StrUtil;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.bookocean.application.exception.BusinessException;
import com.bookocean.application.exception.WeChatErrorCodeEnum;
import com.bookocean.controller.dto.CloudHanPostDto;
import com.bookocean.controller.dto.CommentDto;
import com.bookocean.controller.dto.PageResultDto;
import com.bookocean.domain.repository.BookCommentRepository;
import com.bookocean.infrastructure.persistence.mapper.BookCommentMapper;
import com.bookocean.infrastructure.persistence.mapper.UserInfoMapper;
import com.bookocean.infrastructure.persistence.po.BookCommentPO;
import com.bookocean.infrastructure.persistence.po.UserInfoPO;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Repository;
import org.springframework.transaction.annotation.Transactional;

import java.time.LocalDateTime;
import java.util.ArrayList;
import java.util.List;
import java.util.stream.Collectors;

/**
 * 书摘评论仓储实现类
 * 
 * @author BookOcean
 * @since 2024-01-01
 */
@Slf4j
@Repository
@RequiredArgsConstructor
public class BookCommentRepositoryImpl implements BookCommentRepository {

    private final BookCommentMapper bookCommentMapper;
    private final UserInfoMapper userInfoMapper;

    @Override
    public Integer getCommentCount(Long quoteId) {
        // 参数校验
        if (ObjectUtil.isEmpty(quoteId)) {
            log.warn("获取评论数量失败，书摘ID不能为空: quoteId={}", quoteId);
            return 0;
        }

        try {
            LambdaQueryWrapper<BookCommentPO> queryWrapper = new LambdaQueryWrapper<>();
            queryWrapper.eq(BookCommentPO::getTargetType, 1)
                    .eq(BookCommentPO::getTargetId, quoteId);

            Long count = bookCommentMapper.selectCount(queryWrapper);
            Integer commentCount = count != null ? count.intValue() : 0;
            log.debug("获取评论数量: quoteId={}, count={}", quoteId, commentCount);
            return commentCount;
        } catch (Exception e) {
            log.error("获取评论数量失败: quoteId={}, 错误: {}", quoteId, e.getMessage(), e);
            return 0;
        }
    }

    @Override
    public List<CloudHanPostDto.CommentInfo> getCommentPreview(Long quoteId, Integer limit) {
        // 参数校验
        if (ObjectUtil.isEmpty(quoteId)) {
            log.warn("获取评论预览失败，书摘ID不能为空: quoteId={}", quoteId);
            return new ArrayList<>();
        }

        // 设置默认限制数量
        if (limit == null || limit <= 0) {
            limit = 2;
        }

        try {
            LambdaQueryWrapper<BookCommentPO> queryWrapper = new LambdaQueryWrapper<>();
            queryWrapper.eq(BookCommentPO::getTargetType, 1)
                    .eq(BookCommentPO::getTargetId, quoteId)
                    .orderByDesc(BookCommentPO::getCreatedAt)
                    .last("LIMIT " + limit);

            List<BookCommentPO> comments = bookCommentMapper.selectList(queryWrapper);
            if (comments.isEmpty()) {
                return new ArrayList<>();
            }

            // 转换为DTO并填充用户信息
            List<CloudHanPostDto.CommentInfo> commentInfos = comments.stream()
                    .map(this::convertToCommentInfo)
                    .collect(Collectors.toList());

            log.debug("获取评论预览成功: quoteId={}, limit={}, count={}", quoteId, limit, commentInfos.size());
            return commentInfos;
        } catch (Exception e) {
            log.error("获取评论预览失败: quoteId={}, limit={}, 错误: {}", quoteId, limit, e.getMessage(), e);
            return new ArrayList<>();
        }
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void comment(Long targetId, Integer targetType, Long userId, String content, Long parentId) {
        try {
            BookCommentPO commentPO = new BookCommentPO();
            commentPO.setTargetType(targetType);
            commentPO.setTargetId(targetId);
            commentPO.setUserId(userId);
            commentPO.setContent(content);
            commentPO.setParentId(parentId);
            commentPO.setCreatedAt(LocalDateTime.now());

            int result = bookCommentMapper.insert(commentPO);
            if (result > 0) {
                log.info("创建评论成功: targetId={}, targetType={}, userId={}", targetId, targetType, userId);
            } else {
                log.error("创建评论失败，数据库插入返回0: targetId={}, targetType={}, userId={}", targetId, targetType, userId);
                throw new BusinessException(WeChatErrorCodeEnum.SYSTEM_ERROR);
            }
        } catch (Exception e) {
            log.error("创建评论失败: targetId={}, targetType={}, userId={}, 错误: {}", targetId, targetType, userId, e.getMessage(), e);
            throw new BusinessException(WeChatErrorCodeEnum.SYSTEM_ERROR);
        }
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void replyComment(Long commentId, Long userId, String content) {
        try {
            // 获取原评论信息
            BookCommentPO originalComment = bookCommentMapper.selectById(commentId);
            if (originalComment == null) {
                throw new BusinessException(WeChatErrorCodeEnum.NOT_FOUND, "原评论不存在");
            }

            // 创建回复评论
            BookCommentPO replyPO = new BookCommentPO();
            replyPO.setTargetType(originalComment.getTargetType());
            replyPO.setTargetId(originalComment.getTargetId());
            replyPO.setUserId(userId);
            replyPO.setContent(content);
            replyPO.setParentId(commentId);
            replyPO.setCreatedAt(LocalDateTime.now());

            int result = bookCommentMapper.insert(replyPO);
            if (result > 0) {
                log.info("回复评论成功: commentId={}, userId={}", commentId, userId);
            } else {
                log.error("回复评论失败，数据库插入返回0: commentId={}, userId={}", commentId, userId);
                throw new BusinessException(WeChatErrorCodeEnum.SYSTEM_ERROR);
            }
        } catch (BusinessException e) {
            throw e;
        } catch (Exception e) {
            log.error("回复评论失败: commentId={}, userId={}, 错误: {}", commentId, userId, e.getMessage(), e);
            throw new BusinessException(WeChatErrorCodeEnum.SYSTEM_ERROR);
        }
    }

    @Override
    public Integer countByTarget(Long targetId, Integer targetType) {
        if (ObjectUtil.isEmpty(targetId) || ObjectUtil.isEmpty(targetType)) {
            log.warn("获取评论数量失败，参数不能为空: targetId={}, targetType={}", targetId, targetType);
            return 0;
        }

        try {
            LambdaQueryWrapper<BookCommentPO> queryWrapper = new LambdaQueryWrapper<>();
            queryWrapper.eq(BookCommentPO::getTargetType, targetType)
                    .eq(BookCommentPO::getTargetId, targetId);

            Long count = bookCommentMapper.selectCount(queryWrapper);
            Integer commentCount = count != null ? count.intValue() : 0;
            log.debug("获取评论数量: targetId={}, targetType={}, count={}", targetId, targetType, commentCount);
            return commentCount;
        } catch (Exception e) {
            log.error("获取评论数量失败: targetId={}, targetType={}, 错误: {}", targetId, targetType, e.getMessage(), e);
            return 0;
        }
    }

    @Override
    public PageResultDto<CommentDto> getCommentsByTarget(Long targetId, Integer targetType, Integer page, Integer pageSize) {
        if (ObjectUtil.isEmpty(targetId) || ObjectUtil.isEmpty(targetType)) {
            log.warn("获取评论列表失败，参数不能为空: targetId={}, targetType={}", targetId, targetType);
            return PageResultDto.of(new ArrayList<>(), 0L, page, pageSize);
        }

        try {
            // 计算偏移量
            Integer offset = (page - 1) * pageSize;
            
            // 查询评论列表
            LambdaQueryWrapper<BookCommentPO> queryWrapper = new LambdaQueryWrapper<>();
            queryWrapper.eq(BookCommentPO::getTargetType, targetType)
                    .eq(BookCommentPO::getTargetId, targetId)
                    .isNull(BookCommentPO::getParentId) // 只查询顶级评论
                    .orderByDesc(BookCommentPO::getCreatedAt)
                    .last("LIMIT " + offset + ", " + pageSize);

            List<BookCommentPO> commentPOs = bookCommentMapper.selectList(queryWrapper);
            
            // 查询总数
            LambdaQueryWrapper<BookCommentPO> countWrapper = new LambdaQueryWrapper<>();
            countWrapper.eq(BookCommentPO::getTargetType, targetType)
                    .eq(BookCommentPO::getTargetId, targetId)
                    .isNull(BookCommentPO::getParentId);
            Long total = bookCommentMapper.selectCount(countWrapper);

            // 转换为DTO并填充用户信息
            List<CommentDto> commentDtos = new ArrayList<>();
            for (BookCommentPO commentPO : commentPOs) {
                CommentDto commentDto = convertToCommentDto(commentPO);
                
                // 查询回复列表
                List<CommentDto.ReplyDto> replies = getRepliesByCommentId(commentPO.getCommentId());
                commentDto.setReplies(replies);
                
                commentDtos.add(commentDto);
            }

            log.debug("获取评论列表成功: targetId={}, targetType={}, count={}", targetId, targetType, commentDtos.size());
            return PageResultDto.of(commentDtos, total, page, pageSize);
        } catch (Exception e) {
            log.error("获取评论列表失败: targetId={}, targetType={}, 错误: {}", targetId, targetType, e.getMessage(), e);
            throw new BusinessException(WeChatErrorCodeEnum.SYSTEM_ERROR);
        }
    }

    @Override
    public List<CommentDto.ReplyDto> getRepliesByCommentId(Long commentId) {
        if (ObjectUtil.isEmpty(commentId)) {
            return new ArrayList<>();
        }

        try {
            LambdaQueryWrapper<BookCommentPO> queryWrapper = new LambdaQueryWrapper<>();
            queryWrapper.eq(BookCommentPO::getParentId, commentId)
                    .orderByAsc(BookCommentPO::getCreatedAt);

            List<BookCommentPO> replyPOs = bookCommentMapper.selectList(queryWrapper);
            List<CommentDto.ReplyDto> replyDtos = new ArrayList<>();

            for (BookCommentPO replyPO : replyPOs) {
                CommentDto.ReplyDto replyDto = new CommentDto.ReplyDto();
                replyDto.setId(replyPO.getCommentId());
                replyDto.setContent(replyPO.getContent());
                replyDto.setCreatedAt(replyPO.getCreatedAt());

                // 查询回复用户信息
                CommentDto.UserInfo userInfo = new CommentDto.UserInfo();
                try {
                    UserInfoPO user = userInfoMapper.selectById(replyPO.getUserId());
                    if (user != null) {
                        userInfo.setId(user.getId());
                        userInfo.setNickname(user.getNickName() != null ? user.getNickName() : "匿名用户");
                        userInfo.setAvatar(user.getAvatarUrl());
                        userInfo.setTitle(user.getTitle());
                    } else {
                        userInfo.setNickname("匿名用户");
                    }
                } catch (Exception e) {
                    log.warn("查询回复用户信息失败，userId: {}", replyPO.getUserId());
                    userInfo.setNickname("匿名用户");
                }
                replyDto.setUser(userInfo);

                // 查询回复目标用户（如果是回复其他用户的评论）
                if (replyPO.getParentId() != null && !replyPO.getParentId().equals(commentId)) {
                    try {
                        BookCommentPO parentComment = bookCommentMapper.selectById(replyPO.getParentId());
                        if (parentComment != null) {
                            UserInfoPO parentUser = userInfoMapper.selectById(parentComment.getUserId());
                            if (parentUser != null) {
                                replyDto.setReplyToUser(parentUser.getNickName() != null ? parentUser.getNickName() : "匿名用户");
                            }
                        }
                    } catch (Exception e) {
                        log.warn("查询回复目标用户失败，parentId: {}", replyPO.getParentId());
                    }
                }

                replyDtos.add(replyDto);
            }

            return replyDtos;
        } catch (Exception e) {
            log.error("获取回复列表失败: commentId={}, 错误: {}", commentId, e.getMessage(), e);
            return new ArrayList<>();
        }
    }

    /**
     * 转换评论PO为CommentDto
     * 
     * @param commentPO 评论PO
     * @return CommentDto
     */
    private CommentDto convertToCommentDto(BookCommentPO commentPO) {
        CommentDto commentDto = new CommentDto();
        commentDto.setId(commentPO.getCommentId());
        commentDto.setContent(commentPO.getContent());
        commentDto.setCreatedAt(commentPO.getCreatedAt());

        // 查询用户信息
        CommentDto.UserInfo userInfo = new CommentDto.UserInfo();
        try {
            UserInfoPO user = userInfoMapper.selectById(commentPO.getUserId());
            if (user != null) {
                userInfo.setId(user.getId());
                userInfo.setNickname(user.getNickName() != null ? user.getNickName() : "匿名用户");
                userInfo.setAvatar(user.getAvatarUrl());
                userInfo.setTitle(user.getTitle());
            } else {
                userInfo.setNickname("匿名用户");
            }
        } catch (Exception e) {
            log.warn("查询评论用户信息失败，userId: {}", commentPO.getUserId());
            userInfo.setNickname("匿名用户");
        }
        commentDto.setUser(userInfo);

        return commentDto;
    }

    /**
     * 转换评论PO为CommentInfo DTO
     * 
     * @param commentPO 评论PO
     * @return CommentInfo DTO
     */
    private CloudHanPostDto.CommentInfo convertToCommentInfo(BookCommentPO commentPO) {
        CloudHanPostDto.CommentInfo commentInfo = new CloudHanPostDto.CommentInfo();
        commentInfo.setId(commentPO.getCommentId());
        commentInfo.setUserId(commentPO.getUserId());
        commentInfo.setContent(commentPO.getContent());
        commentInfo.setCreatedAt(commentPO.getCreatedAt());

        // 查询用户昵称
        try {
            UserInfoPO user = userInfoMapper.selectById(commentPO.getUserId());
            if (user != null && StrUtil.isNotBlank(user.getNickName())) {
                commentInfo.setNickname(user.getNickName());
            } else {
                commentInfo.setNickname("匿名用户");
            }
        } catch (Exception e) {
            log.warn("查询评论用户信息失败，userId: {}", commentPO.getUserId());
            commentInfo.setNickname("匿名用户");
        }

        return commentInfo;
    }
}